package com.ssy.lingxi.gateway.serviceimpl;

import com.ssy.lingxi.common.model.dto.UserLoginCacheDTO;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.gateway.handler.exception.LoginException;
import com.ssy.lingxi.gateway.service.ITokenAndAuthService;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Service;
import org.springframework.web.server.ServerWebExchange;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 客户端请求Token和权限验证接口实现
 * @author 王日灿、万宁
 * @version 2.0.0
 * @date 2020-06-07
 */
@Service
public class TokenAndAuthServiceImpl implements ITokenAndAuthService {

    //如果使用StringRedisTemplate注入，要使用@Autowired注解
    //如果指定了RedisTemplate的泛型类，要使用@Resource注解
    @Resource
    private RedisTemplate<String, UserLoginCacheDTO> redisTemplate;

    /**
     * 前端请求包含在Http Headers中的Token的Key
     */
    private static final  String TOKEN_AUTHORIZATION_KEY = "token";

    /**
     * 前端请求包含在Http Headers中的会员Id的Key
     */
    private static final String MEMBER_AUTHORIZATION_KEY = "mid";

    /**
     * 指定不需要进行Token和Auth验证的Url
     */
    private static final List<String> excludeUrlList =
            Stream.of("/oauth/token",
                    "/system/middleground/user/login",
                    "/system/swagger-ui.html",
                    "/member/register/basic",
                    "/menu/member/register/type",
                    "/member/register/type",
                    "/menu/member/register/detail",
                    "/member/register/detail",
                    "/member/login",
                    "/login")
                    .collect(Collectors.toList());

    @Override
    public void authToken(ServerWebExchange serverWebExchange) {

        //todo 怎样获得真实请求路径？
        //请求路径
        String requestPath = serverWebExchange.getRequest().getPath().value();

        //过滤不需要验证的Url
        if (excludeUrlList.contains(requestPath)) {
            return;
        }

        HttpHeaders headers = serverWebExchange.getRequest().getHeaders();

        List<String> tokenList = headers.get(TOKEN_AUTHORIZATION_KEY);
        //验证token是否存在
        if (null == tokenList || tokenList.size() == 0) {
            throw new LoginException(ResponseCode.TOKEN_INEXISTENCE.getMessage(), ResponseCode.TOKEN_INEXISTENCE.getCode());
        }

        //根据token获取用户信息
        UserLoginCacheDTO middlegroundUserLoginResponse = redisTemplate.opsForValue().get(tokenList.get(0));
        if (middlegroundUserLoginResponse == null) {
            throw new LoginException(ResponseCode.TOKEN_DOES_NOT_EXIST_IN_CACHE.getMessage(), ResponseCode.TOKEN_DOES_NOT_EXIST_IN_CACHE.getCode());
        }

        //todo 这里待修改（添加权限验证）
//        List<RoleLoginResponse> roles = middlegroundUserLoginResponse.getRoles();
//        Set<String> menuPaths= new HashSet();
//        roles.forEach(role->{
//            List<MenuLoginResponse> menus = role.getMenus();
//            Set<String> collect = menus.stream().map(menu -> menu.getPath()).collect(Collectors.toSet());
//            menuPaths.addAll(collect);
//        });
//        if(!menuPaths.contains(requestPath)){
//            throw  new LoginException(ResponseCode.INSUFFICIENT_PRIVILEGES.getNameByCode(), ResponseCode.INSUFFICIENT_PRIVILEGES.getCode());
//        }

        return;
    }
}
